package org.example.projecttwo.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.micrometer.common.util.StringUtils;
import org.example.projecttwo.entity.Advertisement;
import org.example.projecttwo.mapper.AdvertisementMapper;
import org.example.projecttwo.service.IAdvertisementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 广告表 服务实现类
 * </p>
 *
 * @author nn
 * @since 2025-11-01
 */
@Service
public class AdvertisementServiceImpl extends ServiceImpl<AdvertisementMapper, Advertisement> implements IAdvertisementService {
    @Override
    public IPage<Advertisement> pageByStatus(Page<Advertisement> page, Integer status, String keyword) {
        LambdaQueryWrapper<Advertisement> queryWrapper = new LambdaQueryWrapper<>();

        // 根据状态查询
        if (status != null && status != 0) {
            queryWrapper.eq(Advertisement::getStatus, status);
        }
        // 根据关键词查询--匹配标题
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.like(Advertisement::getTitle, keyword);
        }
        // 排序
        queryWrapper.orderByDesc(Advertisement::getSortOrder);

        return this.page(page, queryWrapper);
    }

    @Override
    public int countPublishedAds() {
        return Math.toIntExact(this.count(new LambdaQueryWrapper<Advertisement>()//Math.toIntExact()将long转为int
                .eq(Advertisement::getStatus, 2)));
    }

    // 已上架广告数量的最大值
    private static final int MAX_PUBLISHED_ADS = 7;

    @Override
    public void updateStatus(Long id, Integer status) {
        Advertisement existing = this.getById(id);
        if (existing == null) {
            throw new RuntimeException("广告不存在");
        }

        //根据状态决定执行容量检查
        if (status != null && status == 2) {
            //是否为新的【已上架】广告
            boolean isNewPublish = !Objects.equals(existing.getStatus(), 2);
            //针对已上架广告数量检查
            if (isNewPublish) {
                int currentPublished = this.countPublishedAds();
                if (currentPublished >= MAX_PUBLISHED_ADS) {
                    throw new RuntimeException("已上架广告数量已达上限(" + MAX_PUBLISHED_ADS + "条)");
                }
            }
        }

        Advertisement ad = new Advertisement();
        ad.setId(id);
        ad.setStatus(status);
        this.updateById(ad);
    }

    @Override
    public void batchUpdateStatus(List<Long> ids, Integer status) {
        if (CollectionUtils.isEmpty(ids)) return;

        if (status != null && status == 2) {
            List<Advertisement> ads = this.listByIds(ids);
            // 筛选出新的【已上架】广告的数量
            long newPublishCount = ads.stream()
                    .filter(ad -> !Objects.equals(ad.getStatus(), 2))
                    .count();

            if (newPublishCount > 0) {
                int currentPublished = this.countPublishedAds();
                if (currentPublished + newPublishCount > MAX_PUBLISHED_ADS) {
                    throw new RuntimeException("上架后总数将超过" + MAX_PUBLISHED_ADS + "条，请调整选择");
                }
            }
        }

        LambdaUpdateWrapper<Advertisement> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(Advertisement::getId, ids);
        wrapper.set(Advertisement::getStatus, status);
        this.update(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，防止部分更新失败导致顺序错乱
    public void updateSortOrder(List<Long> adIds) {
        List<Advertisement> ads = new ArrayList<>();
        for (int i = 0; i < adIds.size(); i++) {
            Advertisement ad = new Advertisement();
            ad.setId(adIds.get(i));
            ad.setSortOrder(i + 1); // 从1开始排序
            ads.add(ad);
        }
        this.updateBatchById(ads);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    /*
     * newSortOrder: 新的排序序号
     */
    public void updateSingleSortOrder(Long id, Integer newSortOrder) {
        //1. 获取当前排序对象
        Advertisement currentAd = this.getById(id);
        if (currentAd == null) {
            throw new RuntimeException("广告不存在");
        }

        // 获取当前排序对象的序号
        Integer oldSortOrder = currentAd.getSortOrder();
        if (oldSortOrder == null) {
            oldSortOrder = 0;// 处理空值
        }

        //2. 如果新的排序序号和当前排序序号相同，则不需要更新
        if (Objects.equals(oldSortOrder, newSortOrder)) {
            return;
        }

        //3. 获取所有广告的序号（用于边界检查）
        List<Integer> allSortOrders = this.list(new LambdaUpdateWrapper<Advertisement>())
                .stream()
                .map(Advertisement::getSortOrder)// 获取序号
                .filter(Objects::nonNull)// 处理空值
                .toList();// 转为列表

        //4. 确保新序号在合理范围内
        if (newSortOrder < 1) {
            newSortOrder = 1;
        } else if (!allSortOrders.isEmpty()) {
            // 计算最大序号（允许新序号大于当前最大序号）
            int maxSortOrder = allSortOrders.get(allSortOrders.size() - 1);
            if (newSortOrder > maxSortOrder + 1) {
                newSortOrder = maxSortOrder + 1;
            }
        }

        //5. 更新排序序号
        if (newSortOrder < oldSortOrder) {// 向前移动
            // 向前移动：将[newSortOrder, oldSortOrder-1]范围内的广告序号+1
            LambdaUpdateWrapper<Advertisement> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.setSql("sort_order = sort_order + 1")
                    .ge(Advertisement::getSortOrder, newSortOrder)// >=: 全部满足
                    .lt(Advertisement::getSortOrder, oldSortOrder)// <：满足一个
                    .ne(Advertisement::getId, id);// 排除当前广告
            this.update(updateWrapper);
        } else if (newSortOrder > oldSortOrder) {// 向后移动
            // 向后移动：将[oldSortOrder+1, newSortOrder]范围内的广告序号-1
            LambdaUpdateWrapper<Advertisement> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.setSql("sort_order = sort_order - 1")
                    .ge(Advertisement::getSortOrder, oldSortOrder)
                    .lt(Advertisement::getSortOrder, newSortOrder)
                    .ne(Advertisement::getId, id);
            this.update(updateWrapper);
        }

        //6. 更新当前广告的排序序号
        currentAd.setSortOrder(newSortOrder);
        this.updateById(currentAd);
    }
}
